classdef Acquisition < Signal

properties 
	FrequencyLow;
	FrequencyHigh;
	FrequencyStep;
	FrequencyOffset;
	DetectionStatus;
	FrequencyShift;
	TimeShift;
	ProbabilityOfFalseAlarm;
	NumberOfPeriods;
end % end of properties

properties (SetAccess = protected)
	FrequencyVector;
	NumberOfFrequencySteps;
	NoiseStd;
	SignalAmplitude;
	Threshold;
	CCF;
	CCFMax;
end % end of properties

properties (SetAccess = private, GetAccess = private)
	CCFHandle;
	DecideEstimateHandle;
	getThresholdHandle;
end % end of properties

methods
	
	function obj = Acquisition(Name, FrequencyOffset)
		obj = obj@Signal(Name);
		switch (obj.Name)
			case 'E5'
				obj.CCFHandle = @obj.CCFE5;
				obj.DecideEstimateHandle = @obj.DecideEstimateE5;
				obj.getThresholdHandle = @obj.getThresholdE5;
			case 'E5a'
				obj.CCFHandle = @obj.CCFE5a;
				obj.DecideEstimateHandle = @obj.DecideEstimateE5a;
				obj.getThresholdHandle = @obj.getThresholdE5a;
			case 'E5aI'
				obj.CCFHandle = @obj.CCFE5aI;
				obj.DecideEstimateHandle = @obj.DecideEstimateE5aI;
				obj.getThresholdHandle = @obj.getThresholdE5aI;
			case 'E5aQ'
				obj.CCFHandle = @obj.CCFE5aQ;
				obj.DecideEstimateHandle = @obj.DecideEstimateE5aQ;
				obj.getThresholdHandle = @obj.getThresholdE5aQ;
			case 'E5b'
				obj.CCFHandle = @obj.CCFE5b;
				obj.DecideEstimateHandle = @obj.DecideEstimateE5b;
				obj.getThresholdHandle = @obj.getThresholdE5b;
			case 'E5bI'
				obj.CCFHandle = @obj.CCFE5bI;
				obj.DecideEstimateHandle = @obj.DecideEstimateE5bI;
				obj.getThresholdHandle = @obj.getThresholdE5bI;
			case 'E5bQ'
				obj.CCFHandle = @obj.CCFE5bQ;
				obj.DecideEstimateHandle = @obj.DecideEstimateE5bQ;
				obj.getThresholdHandle = @obj.getThresholdE5bQ;
			case 'E1'
				obj.CCFHandle = @obj.CCFE1;
				obj.DecideEstimateHandle = @obj.DecideEstimateE1;
				obj.getThresholdHandle = @obj.getThresholdE1;
			case 'E1b'
				obj.CCFHandle = @obj.CCFE1b;
				obj.DecideEstimateHandle = @obj.DecideEstimateE1b;
				obj.getThresholdHandle = @obj.getThresholdE1b;
			case 'E1c'
				obj.CCFHandle = @obj.CCFE1c;
				obj.DecideEstimateHandle = @obj.DecideEstimateE1c;
				obj.getThresholdHandle = @obj.getThresholdE1c;
			case 'B1'
				obj.CCFHandle = @obj.CCFB1;
				obj.DecideEstimateHandle = @obj.DecideEstimateB1;
				obj.getThresholdHandle = @obj.getThresholdB1;
			otherwise
				error('Unknown signal name');
		end
		obj.FrequencyLow = -6e3;
		obj.FrequencyStep = 100;
		obj.FrequencyHigh = 6e3;
		obj.FrequencyOffset = FrequencyOffset;
		obj.resetFrequencyVector();
	end

	function obj = Acquire(obj, SamplesObj, NumberOfPeriods,...
 												 ProbabilityOfFalseAlarm, SVID, varargin)
		obj.NumberOfPeriods = NumberOfPeriods;
		obj.NoiseStd = sqrt(var(SamplesObj.Data(1:100,1)) * ...
									 SamplesObj.NumberOfSamples/(obj.NumberOfPeriods+1))* ...
									 sqrt(obj.NumberOfPeriods); % TODO
		obj.CCFMax = 0;		
		obj.DetectionStatus = 0;
		obj.ProbabilityOfFalseAlarm = ProbabilityOfFalseAlarm;
		ccf = zeros(2*SamplesObj.NumberOfSamples/(obj.NumberOfPeriods+1),...
	 							obj.NumberOfPeriods);
		for i=1:obj.NumberOfFrequencySteps
			for k=1:obj.NumberOfPeriods
				ccf(:, k) = obj.CCFHandle(SamplesObj, ...
																obj.FrequencyVector(i), SVID, k, varargin{:});
			end
			obj.DecideEstimateHandle(ccf, obj.FrequencyVector(i), SamplesObj);
		end
	end

	function obj = set.ProbabilityOfFalseAlarm(obj, val)
		obj.ProbabilityOfFalseAlarm = val;
		obj.getThresholdHandle();
	end

end % end of methods

methods (Access = private)

	function obj = resetFrequencyVector(obj)
		obj.FrequencyVector = obj.FrequencyLow:obj.FrequencyStep:obj.FrequencyHigh;
		obj.FrequencyVector = obj.FrequencyVector + obj.FrequencyOffset;
		obj.NumberOfFrequencySteps = length(obj.FrequencyVector);
	end

	function out = CCFE5(obj, SamplesObj, Frequency, ...
														PrimaryPRNCodeObjE5aI, ...
														PrimaryPRNCodeObjE5aQ, ...
														PrimaryPRNCodeObjE5bI, ...
														PrimaryPRNCodeObjE5bQ)
	end

	function out = CCFE5a(obj, SamplesObj, Frequency, SVID, PeriodNumber, ...
														PrimaryPRNCodeObjE5aI, ...
														PrimaryPRNCodeObjE5aQ)
		Nhalf = SamplesObj.NumberOfSamples/(obj.NumberOfPeriods+1);
		N = 2*Nhalf;
		Tp = SamplesObj.SamplingPeriod;
		k = PeriodNumber;
		exp_vec = exp(2*pi*j*Frequency*(1:N)*Tp).';
		data_vec = SamplesObj.Data(((k-1)*Nhalf +1):(k*Nhalf + Nhalf), 1);
		c1 = -2*PrimaryPRNCodeObjE5aQ.UpsampledCodes(SVID,:)+1;
		c2 = -2*PrimaryPRNCodeObjE5aI.UpsampledCodes(SVID,:)+1;
		c1full = [c1 zeros(1, Nhalf) ];
		c2full = [c2 zeros(1, Nhalf) ];
		out1 = ifft( fft(data_vec) .* conj(fft((j*c1full).' .* exp_vec)));
		out2 = ifft( fft(data_vec) .* conj(fft((  c2full).' .* exp_vec)));
		out = abs(out1) + abs(out2); 
	end

	function out = CCFE5aI(obj, SamplesObj, Frequency, SVID, PeriodNumber, ...
														PrimaryPRNCodeObjE5aI)
		Nhalf = SamplesObj.NumberOfSamples/(obj.NumberOfPeriods+1);
		N = 2*Nhalf;
		Tp = SamplesObj.SamplingPeriod;
		k = PeriodNumber;
		exp_vec = exp(2*pi*j*Frequency*(1:N)*Tp).';
		data_vec = SamplesObj.Data(((k-1)*Nhalf +1):(k*Nhalf + Nhalf), 1);
		c = -2*PrimaryPRNCodeObjE5aI.UpsampledCodes(SVID,:)+1;
		cfull = [c zeros(1, Nhalf) ];
		out = abs(ifft( fft(data_vec) .* conj(fft((cfull).' .* exp_vec))));
	end

	function out = CCFE5aQ(obj, SamplesObj, Frequency, SVID, PeriodNumber,  ...
														PrimaryPRNCodeObjE5aQ)
		Nhalf = SamplesObj.NumberOfSamples/(obj.NumberOfPeriods+1);
		N = 2*Nhalf;
		Tp = SamplesObj.SamplingPeriod;
		k = PeriodNumber;
		exp_vec = exp(2*pi*j*Frequency*(1:N)*Tp).';
		data_vec = SamplesObj.Data(((k-1)*Nhalf +1):(k*Nhalf + Nhalf), 1);
		c = -2*PrimaryPRNCodeObjE5aQ.UpsampledCodes(SVID,:)+1;
		cfull = [c zeros(1, Nhalf) ];
		out = abs(ifft( fft(data_vec) .* conj(fft((j*cfull).' .* exp_vec))));
	end

	function out = CCFE5b(obj, SamplesObj, Frequency, SVID, PeriodNumber, ...
														PrimaryPRNCodeObjE5bI, ...
														PrimaryPRNCodeObjE5bQ)
		out = obj.CCFE5a(SamplesObj, Frequency, SVID, PeriodNumber, ...
										PrimaryPRNCodeObjE5bI, ...
										PrimaryPRNCodeObjE5bQ);
	end

	function out = CCFE5bI(obj, SamplesObj, Frequency, SVID, PeriodNumber,  ...
														PrimaryPRNCodeObjE5bI)
		out = obj.CCFE5aI(SamplesObj, Frequency, SVID, PeriodNumber, ...
										PrimaryPRNCodeObjE5bI);
	end

	function out = CCFE5bQ(obj, SamplesObj, Frequency, SVID, PeriodNumber,  ...
														PrimaryPRNCodeObjE5bQ)
		out = obj.CCFE5aQ(SamplesObj, Frequency, SVID, PeriodNumber, ...
										PrimaryPRNCodeObjE5bQ);
	end
	
	function out = CCFB1(obj, SamplesObj, Frequency, SVID, PeriodNumber, ...
														PrimaryPRNCodeObjB1)
		out = obj.CCFE5aI(SamplesObj, Frequency, SVID, PeriodNumber, ...
										PrimaryPRNCodeObjB1);
	end


	function out = CCFE1(obj, SamplesObj, Frequency, SVID, PeriodNumber, ...
														PrimaryPRNCodeObjE1b, ...
														PrimaryPRNCodeObjE1c)
		Nhalf = SamplesObj.NumberOfSamples/(obj.NumberOfPeriods +1);
		N = 2*Nhalf;
		Tp = SamplesObj.SamplingPeriod;
		k = PeriodNumber;
		Rs = 1/PrimaryPRNCodeObjE1b.ChipPeriod;
		exp_vec = exp(2*pi*j*Frequency*(1:N)*Tp);
		data_vec = SamplesObj.Data(((k-1)*Nhalf +1):(k*Nhalf + Nhalf), 1);
		sc_vec = sign(sin(2*pi*Rs*(1:N)*Tp));
		c1 = -2*PrimaryPRNCodeObjE1b.UpsampledCodes(SVID,:)+1;
		c2 = -2*PrimaryPRNCodeObjE1c.UpsampledCodes(SVID,:)+1;
		c1full = [c1 zeros(1, Nhalf) ];
		c2full = [c2 zeros(1, Nhalf) ];
		out1 = ifft( fft(data_vec) .* conj(fft(((c1full))...
								 .* exp_vec .* sc_vec)).');
		out2 = ifft( fft(data_vec) .* conj(fft((- (c2full))...
								 .* exp_vec .* sc_vec)).');
		out = abs(out1) + abs(out2);
	end

	function out = CCFE1b(obj, SamplesObj, Frequency, SVID, PeriodNumber,  ...
														PrimaryPRNCodeObjE1b)
		out = obj.CCFE5aI(SamplesObj, Frequency, SVID, PeriodNumber, ...
										PrimaryPRNCodeObjE1b);
	end

	function out = CCFE1c(obj, SamplesObj, Frequency, SVID, PeriodNumber,  ...
														PrimaryPRNCodeObjE1c)
		out = obj.CCFE5aI(SamplesObj, Frequency, SVID, PeriodNumber, ...
										PrimaryPRNCodeObjE1c);
	end

    % CCF is a sample number * k (chip period) matrix.
	function obj = DecideEstimateE5a(obj, CCF, Frequency, SamplesObj)
		[m n] = size(CCF); % m: sample number, n: k chip period
		ccf_abs = zeros(m, 1);
		for k=1:obj.NumberOfPeriods
			ccf_abs = ccf_abs + CCF(:,k);
		end
		[ccf_max ind] = max(ccf_abs);
		if ((ccf_max > obj.Threshold) && (ccf_max > obj.CCFMax))
			obj.DetectionStatus = 1;
			obj.SignalAmplitude = ccf_max;
			obj.FrequencyShift = Frequency;
			obj.TimeShift = (ind-1)*SamplesObj.SamplingPeriod;
			obj.CCF = ccf_abs;
			obj.CCFMax = ccf_max;
		end
	end

	function obj = DecideEstimateE5aI(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end
	
	function obj = DecideEstimateE5aQ(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end
	
	function obj = DecideEstimateE5b(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end

	function obj = DecideEstimateE5bI(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end

	function obj = DecideEstimateE5bQ(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end

	function obj = DecideEstimateE1(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end

	function obj = DecideEstimateE1b(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end

	function obj = DecideEstimateE1c(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end

	function obj = DecideEstimateB1(obj, CCF, Frequency, SamplesObj)
		obj = obj.DecideEstimateE5a(CCF, Frequency, SamplesObj);
	end

	function obj = getThresholdE5(obj)
	end

	function obj = getThresholdE5a(obj)
		obj.Threshold = 2*obj.NoiseStd *sqrt( -2*log(obj.ProbabilityOfFalseAlarm));
	end

	function obj = getThresholdE5aI(obj)
		obj.Threshold = obj.NoiseStd *sqrt( -2*log(obj.ProbabilityOfFalseAlarm));
	end

	function obj = getThresholdE5aQ(obj)
		obj = obj.getThresholdE5aI();
	end

	function obj = getThresholdE5b(obj)
		obj = obj.getThresholdE5a();
	end

	function obj = getThresholdE5bI(obj)
		obj = obj.getThresholdE5aI();
	end

	function obj = getThresholdE5bQ(obj)
		obj = obj.getThresholdE5aI();
	end

	function obj = getThresholdE1(obj)
		obj = obj.getThresholdE5a();
	end

	function obj = getThresholdE1b(obj)
		obj = obj.getThresholdE5aI();
	end

	function obj = getThresholdE1c(obj)
		obj = obj.getThresholdE5aI();
	end

	function obj = getThresholdB1(obj)
		obj = obj.getThresholdE5aI();
	end

end % end of methods

end % end of class
